<?php

namespace app\common\service;

use app\common\model\AdminRecycle;
use app\common\model\RuinuoDatabase;
use think\facade\Db;
use think\facade\Request;

class Logic
{
    /*获取数据源*/
    function GetSource($field = '')
    {
        $data = [];
        if ($field) {
            $layout = explode(',', $field);
            foreach ($layout as $k => $v) {
                if ($v) {
                    $options_num = explode('|', $v);
                    $data[$options_num[0]] = GetOptions($v);
                }
            }
        }
        return $data;
    }

    /*自动编号*/
    public function GetNumRule($num_rule = [], $database = '')
    {
        $str = '';
        foreach ($num_rule as $kk => $vv) {
            $rule_val = $vv['val'];
            switch ($vv['type']) {
                case 2:
                    $rule_val = str_replace("YYYY", date('Y'), $rule_val);
                    $rule_val = str_replace("MM", date('m'), $rule_val);
                    $rule_val = str_replace("DD", date('d'), $rule_val);
                    $rule_val = str_replace("HH", date('H'), $rule_val);
                    $rule_val = str_replace("II", date('i'), $rule_val);
                    $str .= str_replace("SS", date('s'), $rule_val);
                    break;
                case 3:
                    $str .= $rule_val;
                    break;
                case 4:
                    if ($database) {
                        $val = '10000000000';
                        $max = substr($val, 0, $rule_val + 1);
                        $num = Db::name($database)->count() + 1;
                        if ($num < $max) {
                            $num = str_pad($num, $rule_val, "0", STR_PAD_LEFT);
                        }
                        $str .= $num;
                    }
                    break;
                default:
                    $val = '9999999999';
                    $max = substr($val, 0, $rule_val);
                    $min = substr($max + 1, 0, $rule_val);
                    $str .= rand($min, $max);
            }
        }
        return $str;
    }

    /*关联更新或新增*/
    public function UpdateTable($data = [], $Model = '', $id = 0, $database = [])
    {
        $Model = Db::name($Model);
        $keyFind = $Model->where("id='" . $id . "'")->find();
        foreach ($database as $k => $v) {
            switch ($v['tag']) {
                case "one":
                    $this->UpdateOneTable($data, $Model, $id, $v, $keyFind);//一对一关联更新;
                    break;
                case "designtable":
                    $this->UpdateMoreTable($data, $Model, $id, $v);//子表一对多关联更新;
                    break;
                case "subtable":
                    $this->UpdateSubMode($data, $id, $v);//关联模块更新ID
                    break;
            }
        }
    }

    /*关联模块更新ID*/
    public function UpdateSubMode($data, $id, $item)
    {
        $t = explode('__', $item['field']);
        $value = !empty($data[$t[0]][$t[1]]) ? $data[$t[0]][$t[1]] : '';
        if ($value) {
            $UpData[$item['sub_id']] = $id;
            $where = "" . $item['sub_id'] . "='" . $value . "'";
            Db::name($item['database'])->where($where)->update($UpData);
        }
    }

    /*一对一关联更新*/
    public function UpdateOneTable($data = [], $Model = '', $id = 0, $item = [], $keyFind = [])
    {
        $alias = !empty($item['alias']) ? $item['alias'] : '';
        if (!empty($data[$alias]) && $alias != 'a') {
            $where = '';
            if ($item['type'] == 1) {
                $where = $item['sub_field'] . "='" . $keyFind[$item['key_field']] . "'";
            } else {
                $where = $item['key_field'] . "='" . $keyFind[$item['sub_field']] . "'";
            }
            $find = Db::name($item['database'])->where($where)->count();
            $data[$item['alias']]['update_id'] = $data['a']['update_id'];
            $data[$item['alias']]['update_time'] = $data['a']['update_time'];
            if ($find == 0) {
                if ($item['type'] == 1) {
                    $data[$item['alias']]['id'] = GetSnowID();
                    $data[$item['alias']][$item['sub_field']] = $id;
                    $data[$item['alias']]['create_id'] = $data['a']['update_id'];
                    $data[$item['alias']]['create_time'] = $data['a']['update_time'];
                    Db::name($item['database'])->insert($data[$item['alias']]);
                }
            } else {
                Db::name($item['database'])->where($where)->update($data[$item['alias']]);
            }
        }
    }


    /*Json子表一对多关联更新*/
    public function UpdateMoreTable($data = [], $Model = '', $id = 0, $item = [])
    {

        $t = explode('__', $item['field']);
        $oldData = !empty($data[$t[0]][$t[1]]) ? json_decode($data[$t[0]][$t[1]], true) : [];
        $field = explode(',', $item['str_field']);

        $arrData = [];
        foreach ($oldData as $k => $v) {
            $up = [];
            foreach ($field as $k2 => $v2) {
                $up[$v2] = isset($v[$v2]) ? $v[$v2] : '';
            }
            if (!empty($v['id'])) {
                $up['id'] = $v['id'];
            }
            if ($up) {
                $arrData[] = $up;
            }

        }
        $ids = "0,";
        foreach ($arrData as $k => $v) {
            $v2 = $v;
            $v2[$item['sub_id']] = $id;
            $v2['update_id'] = $data['a']['update_id'];
            $v2['update_time'] = $data['a']['update_time'];
            $count = 0;
            if (!empty($v['id'])) {
                $count = Db::name($item['database'])->where("id='" . $v['id'] . "'")->count();
            }
            if (empty($count)) {
                $v2['create_id'] = $data['a']['update_id'];
                $v2['create_time'] = $data['a']['update_time'];
                $v2['id'] = GetSnowID();
                Db::name($item['database'])->insert($v2);
                $ids .= $v2['id'] . ',';
            } else {
                $ids .= $v['id'] . ',';
                Db::name($item['database'])->where("id='" . $v['id'] . "'")->update($v2);
            }
        }
        Db::name($item['database'])->where("" . $item['sub_id'] . "='" . $id . "' and id NOT IN(" . rtrim($ids, ",") . ")")->update(['is_delete' => 1]);
    }

    public function GetSubTable($database, $alias)
    {
        $data = [];
        foreach ($database as $k => $v) {
            if (!empty($v['alias'])) {
                if ($alias == $v['alias']) {
                    $data = $v;
                }
            }
        }
        return $data;
    }

    public function UpdateField($Model, $params, $database)
    {
        $Model = Db::name($Model);
        $field = $params['field'];
        $Db = $Model;
        $c = explode('__', $field);
        $upField = $params['field'];
        $where = "`id`='" . $params['id'] . "'";
        if (count($c) == 2) {
            $base = $this->GetSubTable($database, $c[0]);
            $Db = Db::name($base['database']);
            $keyFind = $Model->where("`id`='" . $params['id'] . "'")->find();
            if ($base['type'] == 1) {
                $where = $base['sub_field'] . "='" . $keyFind[$base['key_field']] . "'";
            } else {
                $where = $base['key_field'] . "='" . $keyFind[$base['sub_field']] . "'";
            }
            $upField = $c[1];
        }
        $Db->where($where)->Update([$upField => $params['value']]);
        return ['code' => 200, 'msg' => '修改成功', 'data' => []];
    }


    /*新增修改删除*/
    public function Curd($type = 'add', $model = '', $id = 0, $params = [], $database = [])
    {
        $ModelDatabase = new RuinuoDatabase();
        switch ($type) {
            case 'add':
                $params['a']['id'] = GetSnowID();
                $params['a']['create_time'] = date('Y-m-d H:i:s');
                $params['a']['create_id'] = GetToken('id') ?: 0;
                $params['a']['update_time'] = $params['a']['create_time'];
                $params['a']['update_id'] = $params['a']['create_id'];
                $params['a']['tenant_id'] = GetToken('tenant_id') ?: 0;
                Db::name($model)->insert($params['a']);
                $id = $params['a']['id'];
                if (!empty($database)) {
                    $this->UpdateTable($params, $model, $id, $database);//关联更新或新增
                }
                break;
            case 'edit':
                $this->SensitiveLog($model, $params['a'], $id);//敏感字段修改
                $params['a']['update_time'] = date('Y-m-d H:i:s');
                $params['a']['update_id'] = GetToken('id') ?: 0;
                Db::name($model)->where("id='" . $id . "'")->update($params['a']);
                if (!empty($database)) {
                    $this->UpdateTable($params, $model, $id, $database);//关联更新或新增
                }
                break;
            case 'delete':
                $Set = $ModelDatabase->where("name='" . $model . "'")->field("delete_type,del_log")->findOrEmpty()->toArray();
                if ($Set['del_log'] == 1) {
                    $recycle = Db::name($model)->where("id in(" . $id . ")")->select()->toArray();
                    foreach ($recycle as $k => $v) {
                        $upData = [
                            'table_name' => $model,
                            'app' => strtolower(app('http')->getName()),
                            'controller' => strtolower(Request::controller()),
                            'action' => strtolower(Request::action()),
                            'delete_ip' => Request::ip(),
                            'delete_id' => $v['id'],
                            'delete_type' => $Set['delete_type'],
                            'delete_data' => json_encode($v, JSON_UNESCAPED_UNICODE),
                            'id' => GetSnowID(),
                            'create_time' => date('Y-m-d H:i:s'),
                            'create_id' => GetToken('id') ?: 0,
                            'update_time' => date('Y-m-d H:i:s'),
                            'update_id' => GetToken('id') ?: 0,
                            'tenant_id' => GetToken('tenant_id') ?: 0,
                        ];
                        Db::name("admin_recycle")->insert($upData);
                    }
                }
                switch ($Set['delete_type']) {
                    case 1:
                        Db::name($model)->where("id in(" . $id . ")")->delete();
                        break;
                    case 2:
                        Db::name($model)->where("id in(" . $id . ")")->update(['is_delete' => 1]);
                        break;
                }
                break;
            case 'update_field':
                $this->UpdateField($model, $params, $database);
                break;
        }
        return $id;
    }


    /*记录敏感日志*/
    public function SensitiveLog($model = '', $params = [], $id = 0)
    {
        $ModelDatabase = new RuinuoDatabase();
        $Set = $ModelDatabase->where("name='" . $model . "'")->field("sensitive_field,is_sensitive,comment,field")->findOrEmpty()->toArray();
        $AllField = !empty($Set['field']) ? json_decode($Set['field'], true) : [];
        $FiledFind = [];
        foreach ($AllField as $k => $v) {
            $FiledFind[$v['field']] = $v['title'];
        }
        $is_sensitive = !empty($Set['is_sensitive']) ? $Set['is_sensitive'] : 2;
        if ($is_sensitive == 1) {
            $logField = !empty($Set['sensitive_field']) ? json_decode($Set['sensitive_field'], true) : [];
            $find = Db::name($model)->where("id='" . $id . "'")->find();
            foreach ($logField as $field => $val) {
                if (isset($params[$field])) {
                    if ($params[$field] != $find[$field]) {
                        $upData = [
                            'data_id' => $id,
                            'name' => $model,
                            'comment' => $Set['comment'],
                            'update_before' => $find[$field],
                            'update_after' => $params[$field],
                            'field_name' => $field,
                            'field_comment' => !empty($FiledFind[$field]) ? $FiledFind[$field] : '',
                            'datas' => json_encode($find, JSON_UNESCAPED_UNICODE),
                            'id' => GetSnowID(),
                            'create_time' => date('Y-m-d H:i:s'),
                            'create_id' => GetToken('id') ?: 0,
                            'update_time' => date('Y-m-d H:i:s'),
                            'update_id' => GetToken('id') ?: 0,
                            'tenant_id' => GetToken('tenant_id') ?: 0,
                            'app' => strtolower(app('http')->getName()),
                            'controller' => strtolower(Request::controller()),
                            'action' => strtolower(Request::action()),
                            'ip' => Request::ip()
                        ];
                        Db::name("admin_sensitive")->insert($upData);
                    }
                }
            }
        }
    }
}